extends "AzurChara.gd"

var cost = 0		#魔方消耗


var summoner
var xfSkillFlag = true

#是否使用过金刚钻
var jgzFlag = false
#装备射速
var spd = 0.0
#现代化改造
var upgraded = 0	

var prefer

func _extInit():
	._extInit()
	if team == 1 and rndId == 0 and not isSumm:
		rndId = omgCtrl.generateChaId()
	tpViewInit()	
	atkEff = "atk_gongJian"
	initAttInfo()

	if torpFlag and getSkill("torpedo") == null:
		addCdSkill("torpedo", 5)

func initAttInfo():
	attInfox._init()
	attInfox.atkRan = 3
	attInfox.cri = 0.2

func sortByDistance(a,b):
	return cellRan(a.cell,cell) < cellRan(b.cell,cell)

func sortByDistanceDesc(a,b):
	return cellRan(a.cell,cell) > cellRan(b.cell,cell)	

func sortByFront(a,b):
	if team == 1:
		return a.cell.x > b.cell.x
	else:
		return a.cell.x < b.cell.x

#周围一格
func getAroundChas(cell, allys = true, exCha = null):
	var chas = []
	for i in config.aroundCells:
		var cha = matCha(cell+i)
		if cha != null && (allys && cha.team == team || not allys && cha.team != team):
			chas.append(cha)
	if exCha != null and not chas.has(exCha):chas.append(exCha)
	return chas
#周围十字范围
var nearCells = [Vector2(-1,0),Vector2(1,0),Vector2(0,1),Vector2(0,-1)]
func getNearChas(cell, allys = true, exCha = null):
	var chas = []
	for i in nearCells:
		var cha = matCha(cell+i)
		if cha != null && (allys && cha.team == team || not allys && cha.team != team):
			chas.append(cha)
	if exCha != null and not chas.has(exCha):chas.append(exCha)		
	return chas

#移动特效
func ying(pos):
	var l:Vector2 = pos - position
	var s = 25
	var rs = preload("res://core/ying.tscn")
	var n = l.length()/s
	for i in range(n):
		var spr = rs.instance()
		sys.main.map.add_child(spr)
		spr.texture = img.texture
		spr.position = position + s * (i+1) * l.normalized() - Vector2(img.texture.get_width()/2,img.texture.get_height())
		spr.init(255/n * i + 100)

#默认1敌人
func getFirstCha(team = 1, key = "sortByMaxHp", excludeSiren = false, eraseMe = false, excludeSumm = false):
	var chas = getAllChas(team)
	if eraseMe:chas.erase(self)
	if chas == null or chas.empty():return null

	if not sys.has_method(key):
		chas.sort_custom(self, key)
	else:
		chas.sort_custom(sys, key)
	for i in chas:
		if i.isDeath or i.att.hp < 0:
			continue
		if excludeSiren and i.camp == "塞壬":
			continue
		if excludeSumm and i.isSumm:
			continue
		return i
	return null
	
func _onKillChara(atkInfo:AtkInfo):
	._onKillChara(atkInfo)
	if not atkInfo.hitCha.isSumm:
		killNum += 1

	var cha = self
	if cha.isSumm:
		var summoner = get("summoner")
		if summoner != null:
			cha = summoner
			summoner.killNum += 1
		else:
			cha = null

	if cha != null:
		var statis = azurCtrl.getStatisByCha(cha)
		utils.dicPlus(statis, "kill", 1)


func _onBattleStart():
	._onBattleStart()
	enableDeath = true
	damageData = {}
	dpsData = {}
	hurtData = {}
	skillNum = {}
	emit_signal("onBattleStart")
	yield(reTimer(0.1),"timeout")
	call("onBattleStartEx")

#回合开始时：延迟启动
func onBattleStartEx():
	pass

func _upS():
	._upS()
	if isDeath:return
	emit_signal("upS")
	#血量为负时，执行补偿机制
	if att.hp <= 0:
		changeShield(-shield)
		hurtChara(self, 0, Chara.HurtType.REAL, Chara.AtkType.EFF)
	if att.maxHp <= 0 and att.hp > 0:
		changeShield(-shield)
		att.hp = 0
		hurtChara(self, 0, Chara.HurtType.REAL, Chara.AtkType.EFF)
	#超时加伤机制
	if sys.main.battleTime > 100:
		var bf = hasBuff("b_atkR_diff")
		if bf == null:
			bf = addBuff(buff.b_atkR_diff.new(0.1))
		else:
			bf.att.atkR += 0.01
			if att.reHp > -0.2:
				bf.att.reHp -= 0.01

#战斗时间
var battleTime = 0				
var hasL2d = false
var showL2d = false
var animate = null
var showPic = true
func chaInfo(cha):
	var charaInfos = []
	for i in sys.get_node("/root/topUi").get_children():
		if i.name.find("charaInfoMsg") > -1:charaInfos.append(i)
	var charaInfo = charaInfos.pop_back()

	var btnBoxR = utils.createHBox(charaInfo, Vector2(900, 600))
	btnBoxR.name = "btnBoxR"
	var btnBoxL = utils.createHBox(charaInfo, Vector2(100, 600))
	btnBoxL.name = "btnBoxL"
	
	charaInfo.get_node("Button").hide()
	utils.createItemButton(btnBoxR, self, "战斗详情", "battleDetail", [cha, charaInfo])
	utils.createItemButton(btnBoxR, self, "状态统计", "buffDetail", [cha, charaInfo])

	if cha.type == sys.CharaClass.CVL or cha.type == sys.CharaClass.CV:
		var window = utils.createWindowDialog(charaInfo, "提示", Vector2(600, 400))
		utils.createItemButton(btnBoxR, self, "查看机组", "viewCrew", [cha, window])
	if team == 2:return
	if plus != null:
		var picBtn = utils.createItemButton(btnBoxL, self, "显示立绘", "switchDrawing", [cha, charaInfo], null, null, true)
		if showPic:
			picBtn.text = "关闭立绘"
			if not hasL2d and not showL2d:
				showDrawing(charaInfo)
				
	utils.createItemButton(btnBoxL, self, "角色评论", "charaComments", [charaInfo])
	if isInManual():return			

	# utils.createItemButton(btnBoxR, self, "校准射程", "changeAtkRan", [charaInfo])
	if ename == "tianying" and lv >= 3:
		utils.createItemButton(btnBoxL, self, "吞噬装备", "eatItem", [])
	if hasL2d:
		var liveBtn = utils.createItemButton(btnBoxL, self, "显示Live2D", "switchLive", [charaInfo], null, null, true)
		if live != null and hasL2d and showL2d:
			showL2d(charaInfo)
			liveBtn.text = "关闭Live2D"

	if cha.team == 1:
		utils.createItemButton(btnBoxL, self, "脱下装备", "removeAllEquip", [])
	if lv < 4 and team == 1:
		utils.createItemButton(charaInfo, self, "  角色进化！  ", "showAlEvo", [charaInfo], Vector2(700, 600))

	if lv == 4 and not upgraded and get("upText1") != null:
		utils.createItemButton(btnBoxR, self, "现代化改造", "showUpgrade", [charaInfo])

	if skillSlot == null and lv >= 3:
		utils.createItemButton(btnBoxL, self, "技能学习", "learnSkill", [charaInfo])

	if lv < 4:
		utils.createItemButton(btnBoxR, self, "随机进化", "showRndEvo", [charaInfo])

	

func showRndEvo(charaInfo):
	var chas = []
	for i in utils.getReadyChas():
		if chas.size() >= 2:break
		if i.lv == lv and i != self and i.type != sys.CharaClass.NPC:
			chas.append(i)
	if chas.size() < 2:
		sys.newBaseMsg("警告", "条件不足：需消耗场下两个同等级的角色以进行随机进化！")
		return
	
	for i in chas:
		i.removeAllEquip()
		i.deleteSelf()

	var rndId = chaData.getLvIds(sys.rndListItem(chaData.shipTypeDic.get(type)).id, lv)
	while rndId == id:
		rndId = chaData.getLvIds(sys.rndListItem(chaData.shipTypeDic.get(type)).id, lv)
	rndId = chaData.getLvIds(rndId, lv + 1)
	sys.main.evoCha(self, rndId, false)
	charaInfo.hide()
	
func checkSureEvo():
	return not (lv == 1 and azurCtrl.buli < 1 or lv == 2 and azurCtrl.buli < 3 or lv == 3 and azurCtrl.buli < 9)

var evoWindow
func showAlEvo(charaInfo):
	if is_instance_valid(evoWindow) and evoWindow is WindowDialog:
		evoWindow.queue_free()
		evoWindow = null
	evoWindow = utils.createWindowDialog(charaInfo, "进化", Vector2(1400, 700))

	var context = utils.createScrollContainer(evoWindow, Vector2(1350, 650), Vector2(30, 30))
	var taskBox = utils.createGridContainer(context, 8)
	for i in evos:
		#本体容器
		var vbox = utils.createVBox(taskBox)
		#放入基础单位
		var hBox1 = utils.createHBox(vbox) 
		hBox1.alignment = 1
		hBox1.set_custom_minimum_size(Vector2(200, 100))
		utils.newChaBt(hBox1, i)

		var evoBtn = utils.createItemButton(vbox, self, "进化", "alEvo", [charaInfo, i], Vector2(115, 155))
		var chara = chaData.infoDs[i]
		if chara.evos.size() > 0 and chara.lv < 4:						
			#处理2级单位
			for j in chara.evos:
				# #2级单位容器
				var hBox2 = utils.createHBox(vbox) 
				hBox2.alignment = 1
				utils.newChaBt(hBox2, j.id)

	evoWindow.popup_centered()

func alEvo(charaInfo, id):
	charaInfo.hide()

	var cost = 1
	if lv == 1:cost = 1
	elif lv == 2:cost = 3
	elif lv == 3:cost = 9
	if azurCtrl.buli < cost:
		sys.newBaseMsg("警告", "需要%d个布里！\n[color=#C0C0C0]可通过船坞、商店等途径获得布里"%cost)
		return
	if relic.evoRelic and sys.rndPer(15):
		sys.newBaseMsg("提示", "触发白嫖怪遗物，本次进化不消耗布里！")
	else:
		azurCtrl.changeBuli(-cost)
		
	sys.main.evoChara(self, id)

func showL2d(charaInfo):
	animate = live.getLive(ename)
	charaInfo.add_child(animate)
	animate.play("def")

func switchLive(chaInfo, btn):
	if live == null:
		sys.newBaseMsg("提示", "需要订阅[碧蓝航线Live2D]MOD！")
	if showL2d:
		animate.stop()
		animate.hide()
		btn.text = "显示Live2D"
		showDrawing(chaInfo)
	else:
		if not is_instance_valid(animate):
			showL2d(chaInfo)
		else:
			animate.play()
		btn.text = "关闭Live2D"
		if is_instance_valid(pic):
			pic.hide()
		animate.show()	
	showL2d = !showL2d

#点击角色时调用此函数获得角色信息文本
func getInfo():
	var realLove = "否"
	if realLoveFlag:realLove = "是"
	var res = "            [color=#FFA500]击杀[/color]：{killNum}       [color=#FFA500]阵营[/color]：{camp}       [color=#FFA500]真爱[/color]：{realLove}\n"

	res += "[color=#33ff33]血量：[color=#DC143C]{hp}/{maxHp}[/color]    机动：[color=#DC143C]{dod}[/color]    装甲：[color=#DC143C]{def}({defL}%)[/color]\n"
	
	if mainFlag:
		res += "主炮·{name}  射速：[color=#BDB76B]{spd}%[/color] 伤害:[color=#BDB76B]{dmg}[/color] 射程:[color=#BDB76B]{range}[/color]\n".format({"name":mainName, "spd":int((att.spd)*100), "dmg":mainDmg, "range":att.atkRan})
	if torpFlag:
		res += "鱼雷·{name}  装填：[color=#BDB76B]{cd}[/color]秒 伤害:[color=#BDB76B]{dmg}[/color]\n".format({"name":torpName, "cd":torpCd, "dmg":torpDmg})
	if carrierFlag:
		res += "舰载机·{name}  机组等级：[color=#BDB76B]{lv}[/color]  机库容量：[color=#BDB76B]{rl}[/color]\n".format({"name":crewEquipName, "lv":crewLv, "rl":summLimit})

	# res += "炮击：[color=#DC143C]{atk}[/color]  雷击：[color=#DC143C]{mgiAtk}[/color]  航空：[color=#DC143C]{air}[/color]  冷却：[color=#DC143C]{cd}%[/color] \n".format({"atk":int(att.atk), "mgiAtk":int(att.mgiAtk), "air":int(att.air), "cd":int(att.cd*100)})

	# res += "  伤害修正：[color=#DC143C]{atkR}%[/color]  减伤修正：[color=#DC143C]{defR}%[/color]\n".format({"atkR":int(att.atkR*100), "defR":int(att.defR*100)})

	# res += "暴击：[color=#DC143C]{cri}%[/color]  爆伤：[color=#DC143C]{criR}%[/color]  吸血：[color=#DC143C]{suck}%[/color]  穿透：[color=#DC143C]{pen}%[/color]\n".format({"cri":int(att.cri*100), "criR":int((att.criR+2)*100), "suck":int(att.suck*100), "pen":int(att.penL*100)})
	      
	res += "[table=4][cell]炮击：[color=#DC143C]{atk}[/color][/cell][cell]雷击：[color=#DC143C]{mgiAtk}[/color][/cell][cell]航空：[color=#DC143C]{air}[/color][/cell][cell]冷却：[color=#DC143C]{cd}%[/color][/cell]"

	res += "[cell]暴击：[color=#DC143C]{cri}%[/color][/cell][cell]爆伤：[color=#DC143C]{criR}%[/color][/cell][cell]吸血：[color=#DC143C]{suck}%[/color][/cell][cell]穿透：[color=#DC143C]{pen}%[/color][/cell]"

	res += "[cell]伤害修正：[color=#DC143C]{atkR}%[/color][/cell][cell]减伤修正：[color=#DC143C]{defR}%[/color][/cell][/table]\n"

	res = res.format({
		"killNum":killNum,
		"camp": camp,
		"realLove": realLove,
		"hp":int(att.hp),
		"maxHp":int(att.maxHp), 
		"dod":int(att.dod),
		"def":int(att.def), 
		"defL":int(att.def / (100 + att.def) * 100),
		"atk":int(att.atk), 
		"mgiAtk":int(att.mgiAtk), 
		"air":int(att.air), 
		"cd":int(att.cd*100),
		"cri":int(att.cri*100), 
		"criR":int((att.criR+2)*100), 
		"suck":int(att.suck*100), 
		"pen":int(att.penL*100),
		"atkR":int(att.atkR*100), 
		"defR":int(att.defR*100)
	})

	# for i in skillStrs:
	# 	var tmp = i.rsplit("{tmpName}")
	# 	i = tmp[0]
	# 	if tmp.size() == 2:
	# 		var skName = tmp[1]
	# 		var skData = skillData.get(skName)
	# 		if skData != null:
	# 			var cd = skData.get("cd")
	# 			var id = skData.get("id")
	# 			var sk
	# 			if id != null:
	# 				sk = getSkill(id)
	# 			if sk != null:
	# 				i = i.replace("{cd}", utils.floatScale(sk.cd/(1+att.cd)))
	# 			var dmg = self.getSkillEffect(skName)
	# 			if dmg != null:
	# 				i = i.replace("{damage}", int(dmg))
	# 	res += i + "\n"

	return "[color=%s]%s[/color]" % [config.itemGradeColors[lv - 1], chaName] + res

func getSkillStrs():
	var res = ""
	for i in skillStrs:
		var tmp = i.rsplit("{tmpName}")
		i = tmp[0]
		if tmp.size() == 2:
			var skName = tmp[1]
			var skData = skillData.get(skName)
			if skData != null:
				var cd = skData.get("cd")
				var id = skData.get("id")
				var sk
				if id != null:
					sk = getSkill(id)
				if sk != null:
					i = i.replace("{cd}", utils.floatScale(sk.cd/(1+att.cd)))
				var dmg = self.getSkillEffect(skName)
				if dmg != null:
					i = i.replace("{damage}", int(dmg))
		res += i + "\n"
	return res


func switchDrawing(cha, charaInfo, btn):
	showPic = not showPic
	if showPic:
		btn.text = "关闭立绘"
		if not showL2d:
			showDrawing(charaInfo)
	else:
		btn.text = "显示立绘"
		if is_instance_valid(pic) and pic is TextureRect: 
			pic.queue_free()
			pic = null

func adjustDrawing():
	var width = (pic.texture.get_width() - 500)/2
	pic.rect_position = Vector2(1030-width, 20)

func showDrawing(charaInfo):
	if not is_instance_valid(pic) or not pic is TextureRect:
		pic = utils.getCharaDrawing(self)
		if pic != null:
			adjustDrawing()
			charaInfo.add_child(pic)
	pic.show()

var buffWindow
func buffDetail(cha, charaInfo):
	if is_instance_valid(buffWindow) and buffWindow is WindowDialog:
		buffWindow.queue_free()
		buffWindow = null
	buffWindow = utils.createWindowDialog(charaInfo, "状态详情", Vector2(800, 700))
	var context = utils.createScrollContainer(buffWindow, Vector2(750, 650), Vector2(30, 30))
	var taskBox = utils.createGridContainer(context, 3)

	utils.createRichTextLabel("[color=#BDB76B]状态名称", taskBox, Vector2(200, 50))
	utils.createRichTextLabel("[color=#BDB76B]状态类型", taskBox, Vector2(150, 50))
	utils.createRichTextLabel("[color=#BDB76B]剩余时间", taskBox, Vector2(150, 50))

	for i in cha.buffs:
		if i.get("buffName") == null or i.buffName == "" or i.get("type") == config.EQUITYPE_EQUI:continue
		utils.createRichTextLabel("[color=#FFA500]" + i.buffName, taskBox, Vector2(200, 50))
		var type = "[color=#33ff33]增益"
		if i.isNegetive:type = "[color=#DC143C]减益"
		utils.createRichTextLabel(type, taskBox, Vector2(150, 50))
		var life = "无限"
		if i.life != null and i.life > 0:
			life = String(utils.floatScale(i.life))
		utils.createRichTextLabel(life, taskBox, Vector2(150, 50))

	var lb = utils.createRichTextLabel("[color=#C0C0C0]部分增/减益状态不显示，不代表没有(例如天赋、难度的增益效果)", buffWindow, Vector2(700, 150))
	lb.rect_position = Vector2(30, 625)
	buffWindow.popup_centered()

func getCha(cha):
	sys.main.player.addCha(sys.main.newChara(cha.id))

func appendMeta(txt):
	for i in config.bfDir.keys():
		if txt.find(i) > -1:
			txt = txt.replace(i, "[color=#ffff55][url={key}]{key}[/url][/color]".format({"key":i}))
	return txt
		
#机组相关
var crewExp:int = 0
var crewLv:int = 1
var crewMaxLv:int = 10
var crewEquip = "plane-base"
var crewEquipName = "量产型舰载机"
var summLimit:int = 4
var summedCha = []
var summActiveLimit:int = 2
var summExpBonus:int = 1
var crewWindow = null
var carrierFlag = false				#能否装备舰载机
#查看机组
func viewCrew(cha, node):
	if is_instance_valid(crewWindow) and crewWindow is WindowDialog:
		crewWindow.queue_free()
		crewWindow = null
	crewWindow = utils.createWindowDialog(node, "机组信息", Vector2(600, 300))
	var exLv = 0
	var lb = utils.createRichTextLabel("等级：{0}/{1} (每级提高12%血量及三维，需3-4级航母才能升级)".format({"0":crewLv,"1":crewMaxLv + exLv}), crewWindow, Vector2(500, 150))
	lb.rect_position = Vector2(50, 20)
	var chaBt = preload("res://ui/itemBt/itemBt.tscn").instance()
	chaBt.id = crewEquip
	crewWindow.add_child(chaBt)
	chaBt.rect_position = Vector2(200, 40)
	crewWindow.popup_centered()

#起飞舰载机
func summPlane(extendAllItem = false):
	if not extendAllItem and lv == 4:extendAllItem = true
	var activeCount = 0
	for i in summedCha:
		if not i.isDeath:
			activeCount += 1
	if activeCount >= summActiveLimit:
		var sk = getSkill("castPlane")
		sk.nowTime += sk.cd/(1+att.cd) * 0.5
		return null
	if summedCha.size() >= summLimit:
		return
	var cha = summChara(crewEquip)
	if cha == null:return null
	summedCha.append(cha)
	cha.summoner = self
	cha.updateAtt()
	cha.maxItem = maxItem
	for i in items:
		var item = sys.newItem(i.id)
		if i.get("upgraded") == true && i.has_method("upgrade"):
			item.upgrade()
		cha.addItem(item)
		if not extendAllItem:break
	return cha

#召唤单位
signal summChara
func summChara(id, extendItem = false, inEnemy = false):
	var cells
	if inEnemy:
		if team == 1:
			cells = utils.cellsRight
		else:
			cells = utils.cellsLeft
		cells.shuffle()	
	else:
		cells = utils.getAllCells(team)

	var cha = null
	if inEnemy:
		for i in cells:
			if matCha(i) == null:
				cha = newChara(id, i)
				break
	if cha == null:
		cha = newChara(id, self.cell)
	if cha != null:
		cha.isSumm = true
		emit_signal("summChara", cha)
		if extendItem:
			cha.maxItem = maxItem
			for i in items:
				var it = sys.newItem(i.id)
				if it.has_method("toJson"):
					it.fromJson(i.toJson())
				cha.addItem(it)
	return cha

#召唤单位 - 作为敌人出场
func summEnemy(id, extendItem = false):
	var cha = sys.main.newChara(id, 3 - team)
	sys.main.map.add_child(cha)
	var cells = utils.getAllCells(2)
	for i in cells:
		if matCha(i) == null:
			# cha.setCell(i)
			sys.main.setMatCha(i, cha)
			cha.position = sys.main.map.map_to_world(i)
			break
	if extendItem:
		for i in items:
			var item = sys.newItem(i.id)
			if item.has_method("toJson"):
				item.fromJson(i.toJson())
			cha.addItem(item)
	return cha

func _onBattleEnd():
	._onBattleEnd()
	summedCha = []
	emit_signal("onBattleEnd")
	battleTime = 0
	changeShield(-shield)
	forceHurtFlag = false
	attTurn.clear()
	upAtt()

func deleteSelf():
	var node = self.get_parent()
	sys.main.delMatChara(self)
	if node != null and self.isItem:
		node.queue_free()

#新建技能统一封装
func addSkill(text, name, id = null, cd = null, index = -1):
	if id != null and cd != null:
		addCdSkill(id, cd)
	text = text.replace("{damage}", "[color=#DC143C]{damage}[/color]")
	text = text.replace("{cd}", "[color=#DC143C]{cd}[/color]")
	var skillText = "[color=#FFA500][{name}][/color]-{color}{text}[/color]{tmpName}".format({"name":name,"text":text, "color":skillColors[3]})
	skillText += name
	if index == -1:
		addSkillTxt(skillText)
	else:
		skillStrs[index] = skillText

	if skillData.has(name):
		skillData.get(name).text = skillText
	else:
		skillData[name] = {"text":skillText, "name":name, "id":id, "cd":cd}

var skillColors = ["[color=#4080C6]", "[color=#7A70FE]", "[color=#BA7AFF]", "[color=#25BCAF]"]
var skillData = {}
#计算技能效果
func getSkillEffect(name):
	return null

var damageData = {}
var skillNum = {}
var dpsData = {}
var hurtData = {}
func damageCallback(atkInfo):
	if atkInfo.atkType == sys.AtkType.GUN and atkInfo.get("skill") == null:
		doDamageCallback(atkInfo.hurtVal, "炮击", atkInfo.hitCha)
	elif atkInfo.get("skill") != null:
		doDamageCallback(atkInfo.hurtVal, atkInfo.get("skill"), atkInfo.hitCha)
	else:
		doDamageCallback(atkInfo.hurtVal, "其它", atkInfo.hitCha)

func doDamageCallback(dmg, name, hitCha):
	utils.dicPlus(damageData, name, dmg)
	utils.dicPlus(skillNum, name, 1)
	if hitCha == null or not is_instance_valid(hitCha):return
	utils.dicPlus(dpsData, hitCha, dmg)
	utils.dicPlus(hitCha.hurtData, self, dmg)

#来自召唤物的伤害回调
func damageCallback2(atkInfo):
	doDamageCallback(atkInfo.hurtVal, "召唤物", atkInfo.hitCha)

var battleWindow
func battleDetail(cha, charaInfo):
	if is_instance_valid(battleWindow) and battleWindow is WindowDialog:
		battleWindow.queue_free()
		battleWindow = null
	battleWindow = utils.createWindowDialog(charaInfo, "上回合战斗详情", Vector2(450, 550))

	var hbox = utils.createHBox(battleWindow)
	hbox.rect_position = Vector2(20, 20)

	utils.createItemButton(hbox, self, "伤害详情", "dmgDetail")
	utils.createItemButton(hbox, self, "承伤详情", "hurtDetail")

	var statisScroll = utils.createScrollContainer(battleWindow, Vector2(400, 400), Vector2(20, 100))
	var vbox = utils.createVBox(statisScroll)
	vbox.rect_position = Vector2(20, 20)
	vbox.name = "vbox"
	for i in damageData.keys():
		utils.createRichTextLabel("[color=#DC143C]{name}[/color]：伤害{text}， 次数{num}".format({"name":i, "text":int(damageData.get(i)), "num":skillNum.get(i)}), vbox, Vector2(400, 50))
	
	battleWindow.popup_centered()

func dmgDetail():
	var txt = ""
	for i in dpsData.keys():
		var name = i.chaName
		if i.isSumm:name += "(召唤物)"
		txt += "[color=#DC143C]{name}[/color]：     {dmg}\n".format({"name":name, "dmg":int(dpsData.get(i))})
	utils.openHelpWindow(txt)

func hurtDetail():
	var txt = ""
	for i in hurtData.keys():
		var name = i.chaName
		if i.isSumm:name += "(召唤物)"
		txt += "[color=#DC143C]{name}[/color]：     {dmg}\n".format({"name":name, "dmg":int(hurtData.get(i))})
	utils.openHelpWindow(txt)

#是否在图鉴中
func isInManual():
	var father = self.get_parent()
	if father != null:
		return team != 2 && father.get("id") == self.id
	return false

#设置阵营
func setCamp(camp, force = false):
	if self.camp == null or force:
		self.camp = camp

var forceHurtFlag = false
func plusHp(val, veff = true):
	if isDeath:return 
	if not forceHurtFlag and val < 0:
		 return
	val = val * (1 + att.reHp)
	att.hp += val
	if att.hp > att.maxHp:att.hp = att.maxHp
	emit_signal("onPlusHp", val)
	# if veff and val != 0 and difficult.step < 100:
	var eff = newEffIn("plusHp")
	eff.setNorPos(sprcPos)
	eff.setAmount(int(val / att.maxHp * 40))
	if sys.main.isNumVis:
		var node = null
		if isItem:node = newEffIn("numHit")
		else :node = newEff("numHit")
		node.setNorPos(sprcPos)
		node.scale = Vector2(1, 1)
		node.init(val, self)
		node.play("hp")		

func castBuff(cha, buff):
	if cha == null:return
	buff.casCha = self
	return cha.addBuff(buff)

#===============================技能统计相关=======================================
func onHurtEnd(atkInfo):
	.onHurtEnd(atkInfo)
	if atkInfo.finalDmg > 0 && not atkInfo.isMiss and atkInfo.atkCha.team != atkInfo.hitCha.team:
		var fix = atkInfo.hitCha.att.hp
		if atkInfo.atkCha.isSumm and atkInfo.atkCha.get("summoner") != null:
			atkInfo.atkCha.summoner.damageCallback2(atkInfo)
			var atkStatis = azurCtrl.getStatisByCha(atkInfo.atkCha.summoner) 
			atkStatis.damage += atkInfo.finalDmg
			azurCtrl.setStatisByCha(atkInfo.atkCha.summoner, atkStatis)
		if not atkInfo.atkCha.isSumm:
			atkInfo.atkCha.damageCallback(atkInfo)
			var atkStatis = azurCtrl.getStatisByCha(atkInfo.atkCha) 
			atkStatis.damage += atkInfo.finalDmg
			azurCtrl.setStatisByCha(atkInfo.atkCha, atkStatis)
		if not atkInfo.hitCha.isSumm:
			var hitStatis = azurCtrl.getStatisByCha(atkInfo.hitCha)
			hitStatis.hurt += atkInfo.finalDmg
			azurCtrl.setStatisByCha(atkInfo.hitCha, hitStatis)

#增加人物治疗量统计量
func increDealNum(num):
	var statis = azurCtrl.getStatisByCha(self)
	statis.deal += num
	azurCtrl.setStatisByCha(self, statis)
#增加人物伤害统计量
func increDmgNum(num, name = null, hitCha = null):
	var atkStatis = azurCtrl.getStatisByCha(self) 
	atkStatis.damage += num
	azurCtrl.setStatisByCha(self, atkStatis)
	if name == null:name = "其它"
	doDamageCallback(num, name, hitCha)
#增加人物承伤统计量
func increHurtNum(num, name = null, hitCha = null):
	var atkStatis = azurCtrl.getStatisByCha(hitCha) 
	atkStatis.hurt += num
	azurCtrl.setStatisByCha(hitCha, atkStatis)

#强制杀死
func forceKillCha(cha):
	cha.forceHurtSelf(cha.att.maxHp)
	cha.hurtChara(cha, 1, Chara.HurtType.REAL, Chara.AtkType.EFF)

func yieldOnReach(d):
	yield(d,"onReach")

func setAiCha(cha):
	if cha.hasBuff("b_moHu") != null and cha.team != team:
		var chas = getAllChas(1)
		chas.sort_custom(self, "sortByDistance")
		chas.erase(cha)
		for i in chas:
			if i.hasBuff("b_moHu") != null or i.isDeath:continue
			cha = i
			break
	.setAiCha(cha)

func forceHurtSelf(num):
	forceHurtFlag = true
	plusHp(-num/(att.reHp+1))
	forceHurtFlag = false
	hurtChara(self, 1, Chara.HurtType.REAL, Chara.AtkType.EFF)

func updateTmpAtt(att, num, upAtt = true):
	attEx.set(att, attEx.get(att) + num)
	if upAtt:upAtt()

#创建指向性飞行特效
func createFlyEff(from, to, src, onReach = true):
	var d:Eff = newEff(src, from)
	d._initFlyCha(to)
	if onReach:
		yieldOnReach(d)

#创建指向性特效
func createDirectEff(to, src):
	var eff:Eff = newEff(src)
	eff.position = to

#创建自定义特效
func createCustEff(from, src, spd, loop = false, scale = null, pos = null):
	var d1:Eff = sys.newEff("animEff", from)
	d1.setImgs(sys.getBasePath() + "/" + src, spd, loop)
	if scale != null:
		d1.scale *= scale
	if position != null:
		d1.normalSpr.position = pos
	return d1

#进化后继承属性
func extendsEvo(cha):
	if cha.mainId != "":
		spd = cha.spd
		mainName = cha.mainName
		mainDmg = cha.mainDmg
		mainTxt = cha.mainTxt
		mainId = cha.mainId
		if itemSkill.skills.has(mainId): 
			mainSk = itemSkill.skills.get(mainId).new(1)
			mainSk.setCha(self)
		# attEx.spd += spd
	if cha.torpId != "":
		torpName = cha.torpName
		torpDmg = cha.torpDmg
		torpTxt = cha.torpTxt
		torpCd = cha.torpCd
		torpId = cha.torpId
		if itemSkill.skills.has(torpId):
			torpSk = itemSkill.skills.get(torpId).new(1)
			torpSk.setCha(self)
		var sk = getSkill("torpedo")
		if sk != null:
			sk.cd = torpCd

	#继承额外属性
	fuseAttEx(cha.attEx)
	upAtt()
	setCamp(cha.camp, true)
	maxItem = cha.maxItem
	jgzFlag = cha.jgzFlag
	#继承舰载机
	if cha.crewEquip != "plane-base":
		masCha.crewEquip = cha.crewEquip
		masCha.crewEquipName = cha.crewEquipName
	crewExp = cha.crewExp
	if cha.crewLv > 1:
		crewLv = cha.crewLv
	# crewMaxLv = cha.crewMaxLv	

	if cha.has("skillSlot"):
		skillSlot = skillPool.getSkill(cha.skillSlot)
		skillSlot.setCha(self)
		skillStrs.pop_front()
		skillStrs.push_front("{0}[{1}]:{3}".format({"0":"[color=#FFFF00]","1":skillSlot.sname,"3":skillSlot.text}))

#将角色信息转为字典
func toJson():
	var json = {}
	json["id"] = id
	json["chaName"] = chaName
	json["level"] = level
	json["killNum"] = killNum
	json["rndId"] = rndId
	json["crewExp"] = crewExp
	json["crewLv"] = crewLv
	json["crewMaxLv"] = crewMaxLv
	json["crewEquip"] = crewEquip
	json["crewEquipName"] = crewEquipName
	json["attEx"] = attEx.info
	json["maxItem"] = maxItem
	json["deathNum"] = deathNum

	json["mainId"] = mainId
	json["mainName"] = mainName
	json["mainDmg"] = mainDmg
	json["mainTxt"] = mainTxt
	json["spd"] = spd

	json["torpId"] = torpId
	json["torpName"] = torpName
	json["torpCd"] = torpCd
	json["torpDmg"] = torpDmg
	json["torpTxt"] = torpTxt

	json["jgzFlag"] = jgzFlag
	json["camp"] = camp
	json["upgraded"] = upgraded
	json["attEx"] = attEx.info

	if skillSlot != null:
		json["skillSlot"] = skillSlot.sid

	if utils.inBattle(self):
		if oldCell == Vector2(0, 0) or oldCell == null:
			json["cell"] = cell
		else:
			json["cell"] = oldCell

	return json

#从字段中还原角色信息
func fromJson(json, setCell = true):
	chaName = json.get("chaName")
	level = json.get("level")
	killNum = json.get("killNum")
	rndId = json.get("rndId")
	crewExp = json.get("crewExp")
	crewLv = json.get("crewLv")
	# crewMaxLv = json.get("crewMaxLv")
	crewEquip = json.get("crewEquip")
	crewEquipName = json.get("crewEquipName")
	maxItem = json.get("maxItem")
	deathNum = json.get("deathNum")

	mainId = json.get("mainId")
	mainName = json.get("mainName") 
	mainDmg = json.get("mainDmg") 
	mainTxt = json.get("mainTxt") 

	torpId = json.get("torpId") 
	torpName = json.get("torpName") 

	torpCd = json.get("torpCd") 
	torpDmg = json.get("torpDmg") 
	torpTxt = json.get("torpTxt") 

	jgzFlag = json.get("jgzFlag") 
	spd = json.get("spd") 
	upgraded = json.get("upgraded") 
	if upgraded > 0:
		call("upgrade")

	attEx.spd += spd

	setCamp(json.get("camp"), true)
	
	if json.get("mainId")  != "":
		spd = json.spd
		mainName = json.mainName
		mainDmg = json.mainDmg
		mainTxt = json.mainTxt
		mainId = json.mainId
		if itemSkill.skills.has(mainId): 
			mainSk = itemSkill.skills.get(mainId).new(1)
			mainSk.setCha(self)
	if json.get("torpId")  != "":
		torpName = json.torpName
		torpDmg = json.torpDmg
		torpTxt = json.torpTxt
		torpCd = json.torpCd
		torpId = json.torpId
		if itemSkill.skills.has(torpId):
			torpSk = itemSkill.skills.get(torpId).new(1)
			torpSk.setCha(self)
		var sk = getSkill("torpedo")
		if sk != null:
			sk.cd = torpCd
			
	if json.has("cell") and setCell:
		var cl = utils.stringToVector(json.get("cell"))
		cell = cl
		setCell(cell)
		position = sys.main.map.map_to_world(cl)

	if json.has("attEx"):
		var attExInfo = json.get("attEx")
		for i in attExInfo.keys():
			attEx.set(i, attEx.get(i) + attExInfo.get(i))
		upAtt()

	if json.has("skillSlot"):
		skillSlot = skillPool.getSkill(json.skillSlot)
		skillSlot.setCha(self)	
		skillStrs.pop_front()
		skillStrs.push_front("{0}[{1}]:{3}".format({"0":"[color=#FFFF00]","1":skillSlot.sname,"3":skillSlot.text}))

#执行extInit后执行此函数
func postInit():
	if lv == 2:
		attInfox.maxHp *= 1.5
		attInfox.atk *= 1.1
		attInfox.mgiAtk *= 1.1
		attInfox.def += 30
	elif lv == 3:
		attInfox.maxHp *= 2.25
		attInfox.atk *= 1.2
		attInfox.mgiAtk *= 1.2
		attInfox.def += 50
	elif lv == 4:
		attInfox.maxHp *= 3.5
		attInfox.atk *= 1.3
		attInfox.mgiAtk *= 1.3
		attInfox.def += 80
	if team == 2:
		aiAdjust()
	if mainFlag and mainName == "":
		mainDmg = 40
		mainName = "[color=#F8F8FF][默认]152mm连装炮[/color]"
	if torpFlag and torpName == "":
		torpDmg = 100
		torpName = "[color=#F8F8FF][默认]三联装533mm鱼雷[/color]"
		torpCd = 6
	upAtt()	
	if isInManual() and get("upText1") != null:
		showInManual()
	elif upgraded:
		upgrade()
	checkRealLove()	
	fillSkillSlotText()

func postInfoUp():
	if skillSlot != null:
		skillSlot.remove()
		skillSlot.setCha(self)

func fillSkillSlotText():
	if team == 2 or lv < 3 or type == sys.CharaClass.NPC:return
	if skillSlot == null:
		skillStrs.push_front("[color=#7FFF00][随机技能槽]-点击下方技能学习按钮以填充此栏位")
	else:
		skillStrs.push_front("{0}[{1}]:{3}".format({"0":"[color=#FFFF00]","1":skillSlot.sname,"3":skillSlot.text}))

#学习随机技能
var sks = []
func learnSkill(charaInfo):
	if sys.main.player.gold < 150:
		sys.newBaseMsg("警告", "需要200金币才能学习随机技能")
		return
	var skillWindow = utils.createWindowDialog(charaInfo, "学习随机技能", Vector2(1150, 450))
	skillWindow.popup_exclusive = true
	skillWindow.get_close_button().hide()
	var context = utils.createGridContainer(skillWindow, 2, Vector2(50, 50))
	if sks.empty():
		sks = pullSkills()
	for sk in sks:
		utils.createRichTextLabel(utils.consts.colorRed + "[{1}]:{3}".format({"1":sk.sname,"3":sk.text}), context, Vector2(1000, 50))
		utils.createItemButton(context, self, "学习", "doLearnSkill", [sk, charaInfo])
	skillWindow.popup_centered()

func doLearnSkill(sk, charaInfo):
	charaInfo.hide()
	sk.setCha(self)
	skillSlot = sk
	sys.main.player.plusGold(-200)
	skillStrs.pop_front()
	skillStrs.push_front("{0}[{1}]:{3}".format({"0":"[color=#FFFF00]","1":skillSlot.sname,"3":skillSlot.text}))

#抽取3个随机技能
func pullSkills():
	var sks = []
	var skIds = []
	for i in range(3):
		var sk = skillPool.getRndSkill(prefer).new()
		while skIds.has(sk.sid) or sk.excludeChas.has(self.ename):
			sk = skillPool.getRndSkill(prefer).new()
		sks.append(sk)
		skIds.append(sk.sid)
	return sks

#动态调整AI属性
func aiAdjust():
	var step = sys.main.getStep()
	var factor = max(0, 0.45 - step * 0.01)
	if type == sys.CharaClass.BB or type == sys.CharaClass.CA or (type == sys.CharaClass.CL or type == sys.CharaClass.DD) and jinJieData.nowLv < 3:
		attInfox.maxHp *= (1 - factor)
		attInfox.atk *= (1 - factor)
		attInfox.def *= (1 - factor)
		attInfox.mgiAtk *= (1 - factor)
	if type == sys.CharaClass.DD or type == sys.CharaClass.CL: 
		pass
	if type == sys.CharaClass.CV or type == sys.CharaClass.CVL: 
		attInfox.air *= (1 - factor)
		attInfox.maxHp *= (1 - factor)
		if step >= 45 and sys.rndPer(step*0.5):
			var item = sys.newItem("i_ex_equip_plane")
			item.postInit(false)
			addItem(item)

func _castCdSkill(id):
	._castCdSkill(id)
	if id=="torpedo":
		castTorpedo()

func castTorpedo(cha = aiCha):
	if cha == null:
		aiSeekCha()
		cha = aiCha
	createFlyEff(sprcPos, cha, "sk_feiDang")
	azurHurtChara(cha, torpDmg, sys.HurtType.WEAPON, sys.AtkType.TORPEDO, "鱼雷", true)		

func reloadSkill(id):
	var sk = getSkill(id)
	if sk == null:
		print("reloadSkill error: %s 不存在"%id)
		return
	sk.nowTime += sk.cd

#融合AttEx
func fuseAttEx(att):
	for i in self.attEx.info.keys():
		self.attEx.set(i, self.attEx.get(i) + att.get(i))

#弱驱散
func weakDispel(cha, isNegetive, num = 9999):	
	var n = 0
	for j in cha.buffs:
		if isNegetive and not j.isNegetive or not isNegetive and j.isNegetive:continue
		if j.get("type") != config.EQUITYPE_EQUI and j.get("dispel") != 2 and j.get("dispel") != 3:
			j.isDel = true
			n += 1
			if n >= num:
				break

#造成神圣伤害
func holyDmg(cha, num, name):
	if isDeath:return
	var statisNum = min(cha.att.hp, num)
	increDmgNum(statisNum, name, cha)			
	increHurtNum(statisNum, name, cha)
	cha.forceHurtSelf(num)
	hurtChara(cha, 1, sys.HurtType.REAL, sys.AtkType.EFF)

func isWeakBuff(buff):
	return buff.get("type") != config.EQUITYPE_EQUI and buff.dispel == 1

var enableDeath = true
func _onDeath(atkInfo):
	._onDeath(atkInfo)
	if not enableDeath or not isDeath:return
	enableDeath = false
	call("deathWord")

func deathWord():
	sys.main.emit_signal("onCharaDeathWord", self)

var upgradeWindow
func showUpgrade(charaInfo):
	if not is_instance_valid(upgradeWindow) or not upgradeWindow is WindowDialog:
		upgradeWindow = utils.createWindowDialog(charaInfo, "现代化改造", Vector2(1000, 500))
		utils.createRichTextLabel("[color=#BDB76B]说明：\n[color=#C0C0C0]改造需花费300金币(若有真爱成就则减半)，改造选项二需解锁该角色真爱成就，详情请查看控制面板-成就系统", upgradeWindow, Vector2(900, 100), Vector2(30, 30))
		var taskBox = utils.createGridContainer(upgradeWindow, 2)
		taskBox.rect_position = Vector2(50, 150)
		taskBox.set_custom_minimum_size(Vector2(900, 400))
		
		utils.createRichTextLabel(utils.consts.colorRed + get("upText1"), taskBox, Vector2(800, 50))
		utils.createItemButton(taskBox, self, "选择", "doUpgrade", [1, charaInfo])

		utils.createRichTextLabel(utils.consts.colorRed + get("upText2"), taskBox, Vector2(800, 50))
		var btn = utils.createItemButton(taskBox, self, "选择", "doUpgrade", [2, charaInfo])
		if not realLoveFlag:
			btn.disabled = true

	upgradeWindow.popup_centered()

func doUpgrade(index, charaInfo):
	var cost = 300
	if realLoveFlag:
		cost = 150
	if sys.main.player.gold < cost:
		sys.newBaseMsg("警告", "金币不足！")
		charaInfo.hide()
		return
	sys.main.player.plusGold(-cost)
	upgraded = index
	upgrade()
	charaInfo.hide()

#现代化改造
func upgrade():
	if upgraded == 0 or get("upText1") == null:return
	if upgraded == 1:
		addSkillTxt("[color=#C0C0C0][现代化改造]-" + get("upText1"))
	else:
		addSkillTxt("[color=#C0C0C0][现代化改造]-" + get("upText2"))	

func showInManual():
	addSkillTxt("[color=#C0C0C0][现代化改造1]-" + get("upText1"))
	addSkillTxt("[color=#C0C0C0][现代化改造2]-" + get("upText2"))

#真爱成就
var realLoveFlag = false
func checkRealLove():
	if realLoveFlag:return
	var achiChara = base.getSetting("achiChara", {})
	realLoveFlag = achiChara.has(ename)

func removeAllEquip():
	var index = items.size()-1
	while index >= 0:
		var item = items[index]
		delItem(item)
		if item.has_method("clearData"):
			item.clearData()
		index -= 1

var commentWindow
func charaComments(charaInfo):
	if is_instance_valid(commentWindow) and commentWindow is WindowDialog:
		commentWindow.queue_free()
		commentWindow = null
	commentWindow = utils.createWindowDialog(charaInfo, "角色评论", Vector2(1400, 700))
	var context = utils.createScrollContainer(commentWindow, Vector2(1350, 600), Vector2(30, 100))
	context.name = "context"
	utils.createItemButton(commentWindow, self, "刷新", "refreshComments", [], Vector2(30, 30))
	utils.createItemButton(commentWindow, self, "发表", "submitComments", [], Vector2(100, 30))
	refreshComments()
	commentWindow.popup_centered()

func refreshComments():
	var res = net.sendRequest("/azurline/new/comment/%s/get"%ename, HTTPClient.METHOD_GET)
	if res == null:
		print("无返回数据")
		return
	res = JSON.parse(res).result
	if res == null:return
	if res.code != "success":
		print("请求失败")
		return

	var context = commentWindow.get_node("context")
	var lb
	if not context.has_node("lb"):
		lb = utils.createRichTextLabel("", context, Vector2(1200, 500))
		lb.name = "lb"
	else:
		lb = context.get_node("lb")
		lb.bbcode_text = ""
	for i in range(res.data.size()):
		var vo = res.data[i]
		lb.bbcode_text += "#{0}  [color=#008000]{1}[/color]   [color=#C0C0C0]{2}[/color] ：\n          [color=#FFD700]{3}[/color]\n".format({"0":res.data.size()-i, "1":vo.userName, "2":vo.createTime, "3":vo.content})

func submitComments():
	var window = utils.createWindowDialog(commentWindow, "发表评论", Vector2(600, 400))

	var edit = TextEdit.new()
	edit.rect_position = Vector2(50, 20)
	edit.set_custom_minimum_size(Vector2(500, 300))
	window.add_child(edit)

	var b = Button.new()
	b.rect_position = Vector2(280, 330)
	b.text = "确定"
	b.connect("pressed", self, "commentSubmit", [window, edit])
	window.add_child(b)

	window.popup_centered()

func commentSubmit(window, edit):
	var body = {"userName": utils.getPlayerName(), "chaId": self.ename, "content": edit.text, "chaName": self.chaName}
	var res = net.sendRequest("/azurline/new/comment/submit", HTTPClient.METHOD_POST, to_json(body))
	window.hide()
	window.queue_free()
	refreshComments()

